package com.kai.steering.common.web.exception;

import com.kai.steering.common.vo.Result;
import com.kai.steering.common.web.properties.UimpAopProperties;
import com.kai.steering.common.web.vo.ReturnCodeExt;
import com.kai.steering.exception.UimpException;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException;
import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import java.util.List;

/**
 * @ Author     ：LiuKai.
 * @ Date       ：Created in 15:53 2022-3-10
 * @ Description：
 * @ Modified By：
 * @Version:
 */

@ControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {


    protected UimpAopProperties aopProperties;

    @Value("${spring.servlet.multipart.max-file-size:1MB}")
    private String maxFileSize;

    @Value("${spring.servlet.multipart.max-request-size:1MB}")
    private String maxRequestSize;


    @Autowired
    public void setSpringBootPlusAopProperties(UimpAopProperties uimpAopProperties) {
        aopProperties = uimpAopProperties;
    }

    /**
     * 处理文件上传大小超限制
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(value = MultipartException.class)
    public ResponseEntity<Object> fileUploadExceptionHandler(MultipartException exception, WebRequest request) {
        String msg;
        if (exception.getRootCause() instanceof FileSizeLimitExceededException) {
            msg = "上传文件过大[单个文件大小不得超过" + maxFileSize + "]";
        } else if (exception.getRootCause() instanceof SizeLimitExceededException) {
            msg = "上传文件过大[总上传大小不得超过" + maxRequestSize + "]";
        } else {
            msg = "文件上传失败[服务器异常]";
        }

        UimpException ex = ReturnCodeExt.SYSTEM_EXCEPTION.getException(exception, msg);
        return this.handleExceptionInternal(ex, (Object) null, new HttpHeaders(), ex.getStatus(), request);
    }




    @ExceptionHandler({UimpException.class})
    @Nullable
    public ResponseEntity<Object> handleUimpException(UimpException ex, WebRequest request) {
        return this.handleExceptionInternal(ex, (Object) null, new HttpHeaders(), ex.getStatus(), request);
    }


    @ExceptionHandler({Exception.class})
    @Nullable
    public ResponseEntity<Object> handleException(UimpException ex, WebRequest request) {
        return this.handleExceptionInternal(ex, (Object) null, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
    }

    /**
     * 通用的接口映射异常处理方
     */
    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers,
                                                             HttpStatus status, WebRequest request) {

        log.error("统一异常处理.", ex);
        ResponseEntity<Object> result = null;
        String sysid = aopProperties.getSysId();

        Result apiResult = null;
        //其他异常处理
        if (!(ex instanceof UimpException)) {
            ex = ReturnCodeExt.SYSTEM_OTHER_EXCEPTION.getException(ex.getClass().getName(), ex.getMessage());
        }

        UimpException uex = (UimpException) ex;
        apiResult = Result.builder()
                .code(sysid + uex.getCode())
                .message(uex.getMessage())
                .build();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return new ResponseEntity(apiResult, headers, status);
    }

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        BindingResult result = ex.getBindingResult();
        StringBuilder errorMsg = new StringBuilder() ;

        if (result.hasErrors()) {
            List<FieldError> fieldErrors = result.getFieldErrors();
            if(fieldErrors!=null && !fieldErrors.isEmpty()){
                errorMsg.append(fieldErrors.get(0).getDefaultMessage()).append("!");
            }
//            fieldErrors.forEach(error -> {
//                errorMsg.append(error.getDefaultMessage()).append("!");
//            });
        }
        UimpException uex = ReturnCodeExt.PARAMETER_CHECK.getException(ex,errorMsg.toString());
        return this.handleExceptionInternal(uex, (Object) null, new HttpHeaders(), uex.getStatus(), request);
    }

}
